package com.personal.dao.sqlgenerator;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.personal.dao.bean.BaseModel;
import com.personal.dao.configuration.Configuration;
import com.personal.dao.exception.NoPrimaryKeyException;
import com.personal.dao.metadata.DataBaseFieldMetadata;
import com.personal.dao.metadata.DataBasePrimaryKeyMetadata;
import com.personal.dao.metadata.DataBaseTableMetadata;
import com.personal.dao.reflection.MetaObject;
import com.personal.dao.sql.BaseBatchSql;
import com.personal.dao.sql.BatchSql;

/**
 * 批量插入
 * @author cuibo
 *
 */
public class BatchInsertSelective<T extends BaseModel> extends BaseBatchSqlGenerator<T>
{

    public BatchInsertSelective(List<T> records, DataBaseTableMetadata<T> metadata)
    {
        super(records, metadata);
    }

    @Override
    public BatchSql generate()
    {
        // 查找出最大的属性实体
        Set<DataBaseFieldMetadata> maxMetadats = new LinkedHashSet<>();
        // 所有的数据缓存
        Map<T, Map<DataBaseFieldMetadata, Object>> allDatas = new HashMap<>();
        for (T t : records)
        {
        	MetaObject metaObject = Configuration.getInstance().newMetaObject(t);
        	// 校验
        	SqlValidator.validate(metadata, t, metaObject);
            Map<DataBaseFieldMetadata, Object> data = new HashMap<>();
            
            DataBasePrimaryKeyMetadata primaryKey = metadata.getPrimaryKey();
            if (primaryKey != null)
            {
                Object value = metaObject.getValue(primaryKey.getFieldName()); 
                if (value == null)
    			{
            		// 考虑自动生成
                	if (primaryKey.getGenerator() != null)
        			{
                		value = primaryKey.getGenerator().generatorPrimaryKey();
                		metaObject.setValue(primaryKey.getFieldName(), value);
        			}
                	if (value == null)
					{
                		throw new NoPrimaryKeyException(t + "的主键不能为空！");
					}
    			}	
                data.put(primaryKey, value);
                maxMetadats.add(primaryKey);
            }
            for (DataBaseFieldMetadata field : metadata.getFields())
            {
                Object value = metaObject.getValue(field.getFieldName());
                if (value != null)
                {
                    data.put(field, value);
                    maxMetadats.add(field);
                }
            }
            allDatas.put(t, data);
        }
        // 拼接Sql
        StringBuilder before = new StringBuilder("insert into ").append(metadata.getTableName()).append(" (");
        StringBuilder after = new StringBuilder();
        for (DataBaseFieldMetadata field : maxMetadats)
        {
            before.append(field.getColumnName()).append(",");
            after.append("?,");
        }
        before.deleteCharAt(before.length() - 1).append(")").append(" values (");
        before.append(after.deleteCharAt(after.length() - 1)).append(")");
        List<Object[]> datas = new ArrayList<Object[]>();
        for (T t : records)
        {
            Object[] arr = new Object[maxMetadats.size()];
            Map<DataBaseFieldMetadata, Object> local = allDatas.get(t);
            int fieldIndex = 0;
            for (DataBaseFieldMetadata field : maxMetadats)
            {
                arr[fieldIndex ++] = local.get(field);
            }
            datas.add(arr);
        }
        return new BaseBatchSql(before.toString(), datas);
    }

}
